#include <iostream>
#include <sys/types.h>
#include <pthread.h>
#include <unistd.h>
#include <ctime>
#include<string>
#include "ringQueue.hpp"
#include "caculate_task.hpp"
using namespace std;

char opr[] = "+-*/%";
struct threadData{
    threadData(int num)
    :threadName("thread-"+to_string(num))
    {}
    string threadName;
};



ringQueue<caculate_task> queue;

void *productor(void *args) // 生产者
{
    // cout << "produce ..." << endl;
    threadData*data=static_cast<threadData*>(args);
    int z = 0;
    while (1)
    {
        // 生产者生产数据
        int i = rand() % 10;
        usleep(10);
        int j = rand() % 10;
        char op = opr[z % 5];
        z++;
        caculate_task task(i, op, j);
        // 生产好后推送到循环队列也是共享仓库中
        queue.push(task,data->threadName);
        //更改下面位置到上面push函数中，让现象变好看；
        //task.createTask(data->threadName); // 输出现象，证明生产数据成功；
        sleep(1);
    }
    return nullptr;
}

void *consumer(void *args) // 消费者
{
    threadData*data=static_cast<threadData*>(args);
    // cout << "consumer ..." << endl;
    caculate_task getData;
    while (1)
    {
        queue.pop(getData,data->threadName); // 获得数据
        //更改下面两段代码位置到上面的pop函数中去，让现象变好看；
        //getData();          // 获得数据后直接处理数据
        //getData.getAnswer(data->threadName); // 输出现象
    }
    return nullptr;
}

int main()
{
    pthread_t p_tid, c_tid;
    srand((unsigned int)time(nullptr));

    // 单生产消费这样做即可
    //{
    // threadData* data1=new threadData(1);
    // threadData* data2=new threadData(2);
    // pthread_create(&p_tid, nullptr, productor, (void*)data1);
    // pthread_create(&c_tid, nullptr, consumer, (void*)data2);
    //}

    //多生产消费
    vector<pthread_t> per,cer;
    for(int i=0;i<2;i++)
    {
        threadData* data1=new threadData(i);
        pthread_create(&p_tid, nullptr, productor, (void*)data1);
        per.push_back(p_tid);
    }
    
    for(int j=0;j<3;j++)
    {
        threadData* data2=new threadData(j);
        pthread_create(&c_tid, nullptr, consumer, (void*)data2);
        cer.push_back(c_tid);
    }
    void *ret;
    for(auto tid:per)
    {
        pthread_join(tid, &ret);
    }
    for(auto tid:cer)
    {
        pthread_join(tid, &ret);
    }

    return 0;
}
